#include "PluginsManager.h"
#include <QApplication>
#include <QFileInfo>
//!json
#include <QJsonArray>
#include <QJsonObject>

#include "interface/interfaceplugin.h"
#include "interface/DataInputInterface.h"
#include "interface/ShowInterface.h"

QDir PluginsManager::getPulingPath()
{
    //!FIXME 这里的路径后期我想换成可以自动指定的
    QDir path = QDir(qApp->applicationDirPath());
    path.cd("../plugins");
    return path;
}

void PluginsManager::loadAllPlugins()
{
    QDir path = getPulingPath();
    
    //!查找到插件
    foreach (QFileInfo info, path.entryInfoList(QDir::Files | QDir::NoDotAndDotDot)) {
        //qDebug()<<"file info:"<<info.fileName();
        //!扫描所有插件，录入元数据
        scan(info.absoluteFilePath());
    }
    
    //! 加载所有插件
     foreach (QFileInfo info, path.entryInfoList(QDir::Files | QDir::NoDotAndDotDot)){
        loadPlugin(info.absoluteFilePath());
     }
    
}

void PluginsManager::scan(const QString &filePath)
{
    /**
    * 判断排除 是否是库
    * windows: .dll .DLL
    * unix/Linux: .so
    */
	if (!QLibrary::isLibrary(filePath)) {
		qCritical() << "ERROR::scan::" << filePath;
		return;
	}
       
    //!获取元数据（名称依赖）
    QPluginLoader *loader = new QPluginLoader(filePath);
    QJsonObject json = loader->metaData().value("MetaData").toObject();
    
    d->m_name.insert(filePath,json.value("name").toVariant());
    d->m_versions.insert(filePath, json.value("version").toVariant());
    d->m_dependencies.insert(filePath, json.value("dependencies").toArray().toVariantList());
    
    delete loader;
    loader = nullptr;
}

void PluginsManager::loadPlugin(const QString &filePath)
{
    //!判断进入的是否是库
    if(!QLibrary::isLibrary(filePath))
        return;
    
    //!检测插件的依赖（递归调用）
    if(!d->check(filePath))
        return;
    
    //! 加载插件
    QPluginLoader *loader = new QPluginLoader(filePath);
    qDebug()<<"file info:"<<loader->fileName();
    if(loader->load()){
        
        //!如果集成自plugin，则认为是 自己的插件（防止外部插件注入）
        InterfacePlugin *plugin = qobject_cast<InterfacePlugin *>(loader->instance());
        if(plugin)
        {
            d->m_loaders.insert(filePath,loader);
             
            plugin->output("plugin");
            return;//加载了就赶紧跑
        }
        //!数据加载插件
        InputDataInterface *input_plugin = qobject_cast<InputDataInterface *>(loader->instance());
        if(input_plugin)
        {
            d->m_loaders.insert(filePath,loader);
            return;//加载了就赶紧跑
           
        }
        //!数据显示插件
        ShowDataInterface *show_plugin = qobject_cast<ShowDataInterface *>(loader->instance());
        if(show_plugin)
        {
            d->m_loaders.insert(filePath,loader);           
           return;//加载了就赶紧跑
        }
        
        //!当代码能运行到这里就证明这个插件是不认识的。
        qCritical()<<"unknown plugin:"<<loader->fileName()<<"--"<<loader->errorString();//!插件不被承认
        delete loader;
        loader = nullptr;
        
    }else{
        qWarning()<<"Plugin loader failed:"<<loader->fileName()<<"--"<<loader->errorString();
    }
}

void PluginsManager::unloadAllPluings()
{
    foreach (const QString &path, d->m_loaders.keys()) {
        unloadPlugin(path);
    }
}

void PluginsManager::unloadPlugin(const QString &filePath)
{
    QPluginLoader *loader = d->m_loaders.value(filePath);
    //!删除插件并从内部结构中删除
    if(loader->unload()){
        qInfo()<<"unload Plugin"<<d->m_name.value(filePath).toString();
        d->m_loaders.remove(filePath);
        delete loader;
        loader = nullptr;
    }
}

QList<QPluginLoader *> PluginsManager::allPlugins()
{
    return d->m_loaders.values();
}

QPluginLoader *PluginsManager::getPlugin(const QString &name)
{
    return d->m_loaders.value(d->m_name.key(name));
}

QString PluginsManager::getName(QPluginLoader *loader)
{
    qDebug()<<"PluginsManager::getName";
   qDebug()<< d->m_name.value(d->m_loaders.key(loader));
   qDebug()<<d->m_loaders.key(loader);
    return  d->m_name.key(d->m_loaders.key(loader));
}

void PluginsManager::logAllPlugins()
{
    foreach (const QVariant &name, d->m_name.values()) {
        qInfo()<<"plugin name:"<<name.toString();
    }
}

void PluginsManager::initSignalAndSlot()
{
    auto plugins = allPlugins();
    foreach(auto loader,plugins){
        //! 每个插件发送消息到manager，然后 由 manager 根据dest字段 转发
        connect(loader->instance(),SIGNAL(sendMsg2Manager(PluginMetaData)),
                this,SLOT(recMsgfromPlugin(PluginMetaData)));
    }
}

void PluginsManager::recMsgfromPlugin(PluginMetaData metadata)
{
    qInfo()<<"PluginsManager::recMsgfromPlugin:"<<metadata.dest;
    auto loader = getPlugin(metadata.dest);
       if(loader)
       {
           auto interface = qobject_cast<InterfacePlugin*>(loader->instance());;
           if(interface)
           {
               interface->recMsgfromManager(metadata);
           }
          auto InputInterface = qobject_cast<InputDataInterface*>(loader->instance());;
           if(InputInterface)
           {
               InputInterface->recMsgfromManager(metadata);
           }
           auto ShowInterface = qobject_cast<ShowDataInterface*>(loader->instance());;
            if(ShowInterface)
            {
                ShowInterface->recMsgfromManager(metadata);
            }
       }else{
           qWarning()<<"unknown dest:"<<metadata.dest;
       }

}

PluginsManager::PluginsManager()
{

    d= new PluginsManagerPrivate;
}

PluginsManager::~PluginsManager()
{
	if (d != nullptr)
	{
		delete d;
		d = nullptr;
	}
}


